package rexsee.core.style;

import java.lang.reflect.Field;

import rexsee.core.utilities.Utilities;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.widget.Toast;

public class CanvasSheet {

	public String command = "";
	public Paint paint = null;

	public Drawable drawable = null;
	public String path = "";
	public String text = "";
	public String color = "#FFFFFF"; //String|int

	public String from = "0";
	public String to = "360";
	public String mode = "none";
	public String radius = "";
	public String round_x_radius = "";
	public String round_y_radius = "";

	public String x = "0";
	public String y = "0";
	public String z = "0";
	public String x2 = "0";
	public String y2 = "0";
	public String z2 = "0";
	public String x3 = "0";
	public String y3 = "0";
	public String z3 = "0";
	public String x4 = "-1";
	public String y4 = "-1";

	public String factor = "1";

	private final Context mContext;
	private final float mDensity;
	private int scale(int pixel) {
		return Math.round(mDensity * pixel);
	}
	private int getX() {
		return scale(Utilities.getInt(x.toLowerCase().replaceAll("px", ""), 0));
	}
	private int getY() {
		return scale(Utilities.getInt(y.toLowerCase().replaceAll("px", ""), 0));
	}
	private int getZ() {
		return scale(Utilities.getInt(z.toLowerCase().replaceAll("px", ""), 0));
	}
	private int getX2() {
		return scale(Utilities.getInt(x2.toLowerCase().replaceAll("px", ""), 0));
	}
	private int getY2() {
		return scale(Utilities.getInt(y2.toLowerCase().replaceAll("px", ""), 0));
	}
	private int getZ2() {
		return scale(Utilities.getInt(z2.toLowerCase().replaceAll("px", ""), 0));
	}
	public Rect getRect(Canvas canvas) {
		int sx = getX();
		int sy = getY();
		int sx2 = getX2();
		int sy2 = getY2();
		if (sx < 0) sx = canvas.getWidth() + sx;
		if (sy < 0) sy = canvas.getHeight() + sy;
		if (sx2 <= 0) sx2 = canvas.getWidth() + sx2;
		if (sy2 <= 0) sy2 = canvas.getHeight() + sy2;
		return new Rect(sx, sy, sx2, sy2);
	}
	public RectF getRectF(Canvas canvas) {
		int sx = getX();
		int sy = getY();
		int sx2 = getX2();
		int sy2 = getY2();
		if (sx < 0) sx = canvas.getWidth() + sx;
		if (sy < 0) sy = canvas.getHeight() + sy;
		if (sx2 <= 0) sx2 = canvas.getWidth() + sx2;
		if (sy2 <= 0) sy2 = canvas.getHeight() + sy2;
		return new RectF(sx, sy, sx2, sy2);
	}
	public Rect getSrcRect(Bitmap bitmap) {
		int sx = Utilities.getInt(x3.toLowerCase().replaceAll("px", ""), 0);
		int sy = Utilities.getInt(y3.toLowerCase().replaceAll("px", ""), 0);
		int sx2 = Utilities.getInt(x4.toLowerCase().replaceAll("px", ""), 0);
		int sy2 = Utilities.getInt(y4.toLowerCase().replaceAll("px", ""), 0);
		if (sx < 0) sx = bitmap.getWidth() + sx;
		if (sy < 0) sy = bitmap.getHeight() + sy;
		if (sx2 <= 0) sx2 = bitmap.getWidth() + sx2;
		if (sy2 <= 0) sy2 = bitmap.getHeight() + sy2;
		return new Rect(sx, sy, sx2, sy2);
	}
	public Matrix getMatrix() {
		float[] array = new float[9];
		array[0] = Utilities.getFloat(x, 0);
		array[1] = Utilities.getFloat(y, 0);
		array[2] = Utilities.getFloat(z, 0);
		array[3] = Utilities.getFloat(x2, 0);
		array[4] = Utilities.getFloat(y2, 0);
		array[5] = Utilities.getFloat(z2, 0);
		array[6] = Utilities.getFloat(x3, 0);
		array[7] = Utilities.getFloat(y3, 0);
		array[8] = Utilities.getFloat(z3, 0);
		Matrix matrix = new Matrix();
		matrix.setValues(array);
		return matrix;
	}

	@Override
	public CanvasSheet clone() {
		CanvasSheet rtn = new CanvasSheet(mContext);
		Field[] fields = this.getClass().getFields();
		for (int i = 0; i < fields.length; i++) {
			try {
				fields[i].set(rtn, fields[i].get(this));
			} catch (Exception e) {
			}
		}
		return rtn;
	}
	public void toastMatrix(Matrix matrix) {
		float[] f = new float[9];
		matrix.getValues(f);
		String rtn = "";
		for (int i = 0; i < f.length; i++) {
			rtn += f[i] + ",";
		}
		Toast.makeText(mContext, rtn, Toast.LENGTH_LONG).show();
	}

	private CanvasSheet(Context context) {
		mContext = context;
		mDensity = context.getResources().getDisplayMetrics().density;
	}
	public CanvasSheet(Context context, String style) {
		this(context, style, true);
	}
	public CanvasSheet(Context context, String style, boolean loadDrawable) {
		mContext = context;
		mDensity = context.getResources().getDisplayMetrics().density;
		String[] argus = style.split(";");
		for (int i = 0; i < argus.length; i++) {
			if (argus[i].indexOf(":") <= 0) continue;
			String key = argus[i].substring(0, argus[i].indexOf(":")).trim().toLowerCase().replaceAll("\\-", "\\_");
			String value = argus[i].substring(argus[i].indexOf(":") + 1).trim();
			if (value.length() == 0) continue;
			try {
				this.getClass().getField(key).set(this, value);
			} catch (Exception e) {
			}
		}
		paint = new PaintSheet().parse(style).getPaint();
		if (loadDrawable) loadDrawable();
	}
	public void loadDrawable() {
		if (!this.path.equals("")) {
			this.drawable = RexseeDrawable.getDrawable(mContext, null, this.path);
		}
	}
	public void releaseDrawable() {
		if (this.drawable != null && this.drawable instanceof BitmapDrawable) {
			((BitmapDrawable) this.drawable).getBitmap().recycle();
		}
		this.drawable = null;
	}

	public void draw(Canvas canvas) {
		draw(canvas, false);
	}
	public void draw(Canvas canvas, boolean debug) {
		String c = command.trim().toLowerCase();

		//draw
		if (c.equals("color")) {
			PorterDuff.Mode m;
			try {
				m = PorterDuff.Mode.valueOf(mode);
				if (m == null) m = PorterDuff.Mode.SRC;
			} catch (Exception e) {
				m = PorterDuff.Mode.SRC;
			}
			canvas.drawColor(RexseeDrawable.getIntColor(color), m);
		} else if (c.equals("point")) {
			canvas.drawPoint(getX(), getY(), paint);
		} else if (c.equals("line")) {
			canvas.drawLine(getX(), getY(), getX2(), getY2(), paint);
		} else if (c.equals("rect")) {
			canvas.drawRect(getRectF(canvas), paint);
		} else if (c.equals("roundrect")) {
			canvas.drawRoundRect(getRectF(canvas), scale(Utilities.getInt(round_x_radius, 0)), scale(Utilities.getInt(round_y_radius, 0)), paint);
		} else if (c.equals("cycle")) {
			canvas.drawCircle(getX(), getY(), scale(Utilities.getInt(radius, 0)), paint);
		} else if (c.equals("oval")) {
			canvas.drawOval(getRectF(canvas), paint);
		} else if (c.equals("arc")) {
			float f = Utilities.getFloat(from, 0);
			float t = Utilities.getFloat(to, 0);
			canvas.drawArc(getRectF(canvas), f, t - f, false, paint);
		} else if (c.equals("wedge")) {
			float f = Utilities.getFloat(from, 0);
			float t = Utilities.getFloat(to, 0);
			canvas.drawArc(getRectF(canvas), f, t - f, true, paint);
		} else if (c.equals("text")) {
			canvas.drawText(text, getX(), getY(), paint);
		} else if (c.equals("textonarc")) {
			Path path = new Path();
			float f = Utilities.getFloat(from, 0);
			float t = Utilities.getFloat(to, 0);
			path.addArc(getRectF(canvas), f, t - f);
			canvas.drawTextOnPath(text, path, 0, 0, paint);
		} else if (c.equals("bitmap")) {
			if (drawable instanceof BitmapDrawable) {
				Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
				canvas.drawBitmap(bitmap, getSrcRect(bitmap), getRect(canvas), paint);
			} else {
				drawable.setBounds(getRect(canvas));
				drawable.draw(canvas);
			}

			//matrix
		} else if (c.equals("skew")) {
			Matrix matrix = new Matrix();
			matrix.postSkew(Utilities.getFloat(x, 0), Utilities.getFloat(y, 0), getX2(), getY2());
			canvas.concat(matrix);
		} else if (c.equals("scale")) {
			canvas.scale(Utilities.getFloat(x, 0), Utilities.getFloat(y, 0), getX2(), getY2());
		} else if (c.equals("translate")) {
			Camera camera = new Camera();
			camera.translate(getX(), getY(), getZ());
			Matrix matrix = new Matrix();
			camera.getMatrix(matrix);
			float cx = getX2();
			float cy = getY2();
			matrix.preTranslate(-cx, -cy);
			matrix.postTranslate(cx, cy);
			canvas.concat(matrix);
		} else if (c.equals("rotate")) {
			Camera camera = new Camera();
			float dx = Utilities.getFloat(x, 0);
			float dy = Utilities.getFloat(y, 0);
			float dz = Utilities.getFloat(z, 0);
			float cx = getX2();
			float cy = getY2();
			float cz = getZ2();
			if (dx != 0) camera.rotateX(dx);
			if (dy != 0) camera.rotateY(dy);
			if (dz != 0) camera.rotateZ(dz);
			camera.translate(0.0f, 0.0f, cz);
			Matrix matrix = new Matrix();
			camera.getMatrix(matrix);
			matrix.preTranslate(-cx, -cy);
			matrix.postTranslate(cx, cy);
			canvas.concat(matrix);
		} else if (c.equals("matrix")) {
			canvas.concat(getMatrix());
		} else if (c.equals("resetmatrix")) {
			canvas.setMatrix(new Matrix());
		} else {
		}
		if (debug) {
			toastMatrix(canvas.getMatrix());
		}
	}

}
